package Util

import (
	"errors"
	"github.com/gookit/goutil/dump"
	"github.com/xuri/excelize/v2"
	"gopkg.in/ini.v1"
	"strconv"
)

/**
 * Created by Goland
 * User: wkk alisleepy@hotmail.com
 * Time: 2022/4/17 - 15:39
 * Desc: <处理Excel>
 */

type Excel struct {
	business string
}

// Write2Excel 写入Excel
// data 导出的数据信息，二维,内部每条数据格式类似于 {"id":1, "name":"王凯凯"}
func (e *Excel) Write2Excel(data []map[string]string, fileName string, fieldName, fieldDesc []string, style map[string]map[string]string) (string, error) {
	// 最大支持26列，大于26列无法处理 Z->AZ，后续再优化
	if len(fieldName) > 26 {
		return "导出失败，excel最大支持26列", errors.New("当前方法最多支持26列的导出")
	}

	// 1、创建文件， 默认Sheet1
	f := excelize.NewFile()
	// 默认sheet1
	sheet1 := "Sheet1"

	// 设置样式
	if len(style) > 0 {
		for key, item := range style {
			// 如果是设置宽度
			if key == "width" {
				for k, v := range item {
					width, _ := strconv.Atoi(v)
					err := f.SetColWidth(sheet1, k, k, float64(width))
					if err != nil {
						continue
					}
				}
			}
		}
	}

	// 3、写入表头
	titleColNum := 'A' // 本质上是rune(int32)类型，对应值为当前字符串的ASCII码值，所以可以++操作
	for _, val := range fieldDesc {
		// 循环写入文件的第1行，A1，B1，C1。。。。
		err := f.SetCellValue(sheet1, string(titleColNum)+strconv.Itoa(1), val)
		// 列号+1，A->B->C...
		titleColNum++
		if err != nil {
			return "写入表头出错", err
		}
	}

	// 4、写入数据，一条数据写入一行
	for k := range data {
		dataColNum := 'A'
		for _, field := range fieldName {
			// 从第2行开始写入
			err := f.SetCellValue(sheet1, string(dataColNum)+strconv.Itoa(k+2), data[k][field])
			dataColNum++
			if err != nil {
				return "写入数据出错", err
			}
		}
	}

	// 5、保存文件
	filePath := getSavePath() + fileName
	// 根据指定路径保存文件
	if err := f.SaveAs(filePath); err != nil {
		return "保存文件失败", err
	}

	return filePath, nil
}

// 获取
func getSavePath() string {
	// 加载配置文件
	appConfig, err := ini.Load("Conf/app.ini")
	if err != nil {
		dump.P("load app config fail", err)
		// 默认存放目录
		return "Public/storage/"
	}

	// 读取配置文件信息
	return appConfig.Section("save_path").Key("save_path").String()
}
